﻿

using Dicom.Network;
using HuChaHuRen.HeNan.XiangCheng.Common;
using HuChaHuRen.HeNan.XiangCheng.Models;
using HuChaHuRen.HeNan.XiangCheng.Models.Messages;
using HuChaHuRen.HeNan.XiangCheng.Models.Others;
using log4net;
using Newtonsoft.Json;
using PACS.Client.Model;
using Quartz;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Text;
using System.Threading.Tasks;

namespace HuChaHuRen.HeNan.XiangCheng.Upload
{
    public class DicomTransferJob : IJob
    {
        private static readonly log4net.ILog logger = log4net.LogManager.GetLogger("DicomTransferJob");
        private BaseConfig baseCfg = ConfigHelp.GetBaseConfig();


        public void Execute(IJobExecutionContext context)
        {
            Publish("进入 [DicomTransferJob] 方法.");
            PublishStatus("运行中");
            var dbContext = DataProvider.GetNewConn();
            if (dbContext == null)
            {
                PublishError("数据库连接失败,请检查连接字符串.");
                PublishStatus("就绪");
                return;
            }
            else
            {
                dbContext.Ado.CommandTimeOut = 5000;
            }

            int searchRange = baseCfg.UploadRecordDateRange;
            if (searchRange <= 0)
            {
                searchRange = 3;
            }

            DateTime searchStartTime = DateTime.Now.AddDays(-searchRange);

            List<OrgConfig> orgList = baseCfg.OrgConfigs;
            if (orgList == null || orgList.Count == 0)
            {
                PublishError($"未配置机构信息,任务终止.");
                PublishStatus("就绪");

                return;
            }

            List<string> orgIds = orgList.Select(it => it.OrgID).ToList();
            List<OrganizationInfo> orgRecordList = null;
            try
            {
                orgRecordList = dbContext.Queryable<OrganizationInfo>()
                        .In(it => it.Id, orgIds)
                        .ToList();
            }
            catch (Exception ex)
            {
                Publish($"查询‘OrganizationInfo’发生异常:\n{ex.Message}");
                Publish("[DicomTransferJob]Job已终止.");
                PublishStatus("就绪");
                return;
            }

            Publish($"待上传机构'{orgRecordList.Count}'家.\n");

            //DicomClient dicomClient = new DicomClient();
            //dicomClient.NegotiateAsyncOps();
            Dicom.Network.Client.DicomClient dicomClient = null;
            string localAE = baseCfg.PlatformConfig.LocalAE;
            foreach (var org in orgRecordList)
            {
                string hospCode = orgList.FirstOrDefault(it => it.OrgID == org.Id).HospitalCode;
                int succeedCount = 0;
                int failCount = 0;
                Publish($"当前上传机构:'{org.OrgName}'.");

                var prepareUploadImgList = dbContext.Queryable<Patient, Study, Series, ImageFile, HCHR_XiangCheng_UploadRecord, HCHR_XiangCheng_ImageUploadRecord, JC_MachineInfo>((pat, stu, ser, img, studyRecord, imageRecord, mach) => new object[]
                    {
                        JoinType.Left,pat.Id == stu.PatientID,
                        JoinType.Left,stu.Id == ser.StudyID,
                        JoinType.Left,ser.Id == img.SeriesID,
                        JoinType.Left,stu.Id == studyRecord.StudyID,
                        JoinType.Left,img.Id == imageRecord.ImageID,
                        JoinType.Left, stu.MachineName == mach.SheBeiMingCheng
                    })
                    .Where((pat, stu, ser, img, studyRecord, imageRecord, mach) => pat.OrgID == org.Id && stu.CreateTime > searchStartTime)
                    .Where((pat, stu, ser, img, studyRecord, imageRecord, mach) => studyRecord.ReportUploadSucceed == true && img.Id > 0 &&  SqlFunc.IsNullOrEmpty(imageRecord.ID))
                    .OrderBy((pat, stu, ser, img, studyRecord, imageRecord, mach) => mach.BenDiAE)
                    .OrderBy((pat, stu, ser, img, studyRecord, imageRecord, mach) => stu.Id)
                    .Select((pat, stu, ser, img, studyRecord, imageRecord, mach) => new { StuID = stu.Id, AE = mach.BenDiAE, Img = img })
                    .ToList();

                if(prepareUploadImgList == null || prepareUploadImgList.Count == 0)
                {
                    Publish($"当前机构({org.OrgName})没有需要上传的图像记录.");
                    continue;
                }
                else
                {
                    Publish($"待发送的图片{prepareUploadImgList.Count}张。");
                }

                foreach (var item in prepareUploadImgList)
                {
                  

                    if(item.Img == null || item.Img.ImageFileUrl == null)
                    {
                        logger.Info($"图像记录(ImageFile)不存在(StuID={item.StuID})!");
                        continue;
                    }

                    //AE发生变化时，需要重新初始化dicomClient
                    //Image记录按设备AE排序，可减少初始化次数
                    //if (locaAE != item.AE)
                    //{
                    //    locaAE = item.AE;
                        dicomClient = new Dicom.Network.Client.DicomClient(baseCfg.PlatformConfig.CSotreIP,
                                baseCfg.PlatformConfig.CStorePort,
                                false,
                                localAE,
                                baseCfg.PlatformConfig.CStoreAE,
                                4 * 60 * 1000,
                                3* 60 * 1000);
                        dicomClient.NegotiateAsyncOps();
                    //}

                    try
                    {
                        if (item.Img.ImageFileUrl.StartsWith("\\"))
                        {
                            item.Img.ImageFileUrl = item.Img.ImageFileUrl.Substring(1, item.Img.ImageFileUrl.Length - 1);
                        }
                        string fileLocalPath = Path.Combine(baseCfg.LocalWorkDir, item.Img.ImageFileUrl, item.Img.ImageFileName);
                        fileLocalPath += ".dcm";
                        if (File.Exists(fileLocalPath))
                        {
                            logger.Info($"current dcm file:{fileLocalPath}\nCallingAE:{localAE}");

                            
                            dicomClient.AddRequestAsync(new DicomCStoreRequest(fileLocalPath)).Wait();
                            dicomClient.SendAsync().Wait();

                            //dicomClient.AddRequest(new DicomCStoreRequest(fileLocalPath));
                            //dicomClient.Send(baseCfg.PlatformConfig.CSotreIP,
                            //    baseCfg.PlatformConfig.CStorePort,
                            //    useTls: false,
                            //    item.AE,
                            //    baseCfg.PlatformConfig.CStoreAE);

                            Publish($"图片发送成功!");

                            HCHR_XiangCheng_ImageUploadRecord record = new HCHR_XiangCheng_ImageUploadRecord()
                            {
                                StudyID = item.StuID,
                                SeriesID = item.Img.SeriesID,
                                ImageID = item.Img.Id,
                                CreateTime = DateTime.Now,
                                UploadSucceed = true,
                                ErrorMessage = null
                            };
                            AddOrUpdateRecord(record, dbContext);
                            succeedCount += 1;

                        }
                        else
                        {
                            string err = $"dicom文件不存在:\n{fileLocalPath}";
                            PublishError(err);
                            HCHR_XiangCheng_ImageUploadRecord record = new HCHR_XiangCheng_ImageUploadRecord()
                            {
                                StudyID = item.StuID,
                                SeriesID = item.Img.SeriesID,
                                ImageID = item.Img.Id,
                                CreateTime = DateTime.Now,
                                UploadSucceed = false,
                                ErrorMessage = err
                            };
                            AddOrUpdateRecord(record, dbContext);
                            failCount += 1;
                        }
                    }
                    catch (Exception ex)
                    {
                        string err = $"图像发送出现异常情况:\n{ex.Message}\n{ex.InnerException}";
                        PublishError(err);

                        HCHR_XiangCheng_ImageUploadRecord record = new HCHR_XiangCheng_ImageUploadRecord()
                        {
                            StudyID = item.StuID,
                            SeriesID = item.Img.SeriesID,
                            ImageID = item.Img.Id,
                            CreateTime = DateTime.Now,
                            UploadSucceed = false,
                            ErrorMessage = err
                        };
                        AddOrUpdateRecord(record, dbContext);
                        failCount += 1;
                    }
                }

                Publish($"当前机构图像上传结束.\n上传成功'{succeedCount}'条;\n上传失败'{failCount}'条");
            }

            Publish($"所有机构图像上传结束.");
            PublishStatus("就绪");
        }

        private void AddOrUpdateRecord(HCHR_XiangCheng_ImageUploadRecord record,
            SqlSugarClient dbContext)
        {
            if(record.ErrorMessage != null && record.ErrorMessage.Length > 250)
            {
                record.ErrorMessage = record.ErrorMessage.Substring(0, 250);
            }

            bool isExistde = dbContext.Queryable<HCHR_XiangCheng_ImageUploadRecord>()
                .Any(it => it.StudyID == record.StudyID && it.ImageID == record.ImageID);
            if (isExistde)
            {
                //update 
                int count = dbContext.Updateable<HCHR_XiangCheng_ImageUploadRecord>(record)
                    .Where(it => it.StudyID == record.StudyID && it.ImageID == record.ImageID)
                    .ExecuteCommand();
                if(count <= 0)
                {
                    string content = JsonConvert.SerializeObject(record);
                    string fmContent = JsonUtil.BetterJson(content);
                    PublishError($"更新上传记录(ImageUploadRecord)失败,请检查.\n记录内容是:\n{fmContent}");
                }
            }
            else
            {
                //add

                int count = dbContext.Insertable<HCHR_XiangCheng_ImageUploadRecord>(record)
                    .ExecuteCommand();
                if (count <= 0)
                {
                    string content = JsonConvert.SerializeObject(record);
                    string fmContent = JsonUtil.BetterJson(content);
                    PublishError($"新增上传记录(ImageUploadRecord)失败,请检查.\n记录内容是:\n{fmContent}");
                }
            }
        }


        private void Publish(string msg)
        {
            logger.Info(msg);
            MessageHub.DefaultMessageHub.SendMessage<string>(msg);
        }

        private void PublishError(string msg)
        {
            logger.Error(msg);
            MessageHub.DefaultMessageHub.SendMessage<string>(msg);
        }

        private void PublishStatus(string status)
        {
            MessageHub.DefaultMessageHub.SendMessage<JobActivityMessage>(new JobActivityMessage
            {
                JobType = 1,
                Status = status
            });
        }
    }
}
